package com.livelab.java;

import com.livelab.user.Student;
import com.livelab.util.Constant;
import com.livelab.util.MySQLDatabaseUtil;
import com.livelab.util.Utility;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.mail.internet.*;

/**
 * Backing bean to support "createStudent.xhtml"
 * 
 * @author Joey
 */
@ManagedBean
@RequestScoped
public class StudentRegisterBean {
    private String INSERT = "INSERT INTO agsstudent"
            + "(username, password, lastname, firstname, email, courseId, major, whenCreated) "
            + "VALUES (?,?,?,?,?,?,?,?);";
    
    private String confirmPassword; //holds confirmed password on submission
    private Student student;        //student information

    private MySQLDatabaseUtil db;   //database utility
    private UIInput passInput;      //"password" PrimeFaces component
    private UIInput confPassInput;  //"confirmPassword PrimeFaces component
    private UIInput courseIdInput;  //"courseId" PrimeFaces component

    /**
     * Constructor
     */
    public StudentRegisterBean() {
        db = new MySQLDatabaseUtil("localhost/javalivelab9e", "agsuser", "agsuser");
        db.setPreparedStatement(INSERT);
        
        student = new Student();
    }
    
    /*
     * GETTERS
     */
    public String getConfirmPassword() {
        return confirmPassword;
    }
    
    public Student getStudent(){
        return student;
    }

    /*
     * SETTERS
     */
    public void setConfirmPassword(String confirmPassword) {
        this.confirmPassword = confirmPassword;
    }

    public UIInput getPassInput() {
        return passInput;
    }

    public void setPassInput(UIInput newValue) {
        passInput = newValue;
    }

    public UIInput getConfPassInput() {
        return confPassInput;
    }

    public void setConfPassInput(UIInput newValue) {
        confPassInput = newValue;
    }
    
    public void setCourseIdInput(UIInput newValue) {
        courseIdInput = newValue;
    }
    
    public UIInput getCourseIdInput() {
        return courseIdInput;
    }

    /*
     * ACTIONS
     */
    
    /**
     * Uses inputted Student information to create a new student account
     * 
     * @return target return page
     */
    public String registerStudent() {
        java.util.Date today = new java.util.Date();
        java.sql.Timestamp timestamp = new java.sql.Timestamp(today.getTime());
        
        //get student info and request SQL insert
        Object[] params = student.toArray(timestamp);
        if (db.executePreparedStatement(params) == 1) {
            //create a student directory under courseId directory
            if(Utility.makeDir(Constant.AGS_ROOT + student.getCourseId() + "/" + student.getUserName()))
                return ("index");
            else return(null);
        } else {
            return (null);
        }
    }

    /**
     * Check for a match in database for inputted course id. Bound to "courseId"
     * PrimeFaces inputText component
     * 
     * @param context
     * @param component
     * @param value -- course id
     */
    public void validateCourseId(FacesContext context, UIComponent component, Object value) {

        String sql = "SELECT courseId FROM agsinstructor where courseId = '" + (String) value + "';";
        ResultSet rs = db.executeQuery(sql);
        try {
            //if there is not result in database
            if(rs == null || !rs.next()){
                throw new ValidatorException(new FacesMessage("No instructor course id matches"));
            }
        } catch (SQLException ex) {
            throw new ValidatorException(new FacesMessage("ERROR; Try again"));
        }
    }
    
    /**
     * Checks for the two passwords to match. Bound to "confirmPassword" 
     * PrimeFaces inputText component
     * 
     * @param context
     * @param component
     * @param value -- confirm password
     */
    public void validatePassword(FacesContext context, UIComponent component, Object value) {

        String p = ((String) passInput.getLocalValue());
        String c = (String) value;

        //if the passwords don't match, throw message
        if (!p.equals(c)) {
            throw new ValidatorException(new FacesMessage("Passwords must match"));
        }
    }
    
    /**
     * Checks for a valid signup code. Bound to "signUp" PrimeFaces inputText
     * component
     * 
     * @param context
     * @param component
     * @param value -- signup code
     */
    public void validateSignupCode(FacesContext context, UIComponent component, Object value) {
        //if the student signup code doesn't match 'texas123', throw message
        if (!((String) value).equals("texas123")) {
            throw new ValidatorException(new FacesMessage("Enter valid signup code"));
        }
    }
    
    /**
     * Checks for uniqueness of username. Bound to "username" PrimeFaces 
     * inputText component
     * 
     * @param context
     * @param component
     * @param value -- username
     */
    public void validateUsername(FacesContext context, UIComponent component, Object value) {

        String sql = "SELECT username FROM agsstudent where username = '" + (String) value + "';";
        ResultSet rs = db.executeQuery(sql);
        try {
            //if the username is already in the database, throw message
            if(rs != null && rs.next()){
                throw new ValidatorException(new FacesMessage("Student already exists with this username"));
            }
        } catch (SQLException ex) {
            throw new ValidatorException(new FacesMessage("ERROR; Try again"));
        }
    }
    
    /**
     * Validates email address format. Bound to "email" PrimeFaces inputText 
     * component
     * 
     * @author Jason
     * @param context
     * @param component
     * @param value -- email
     */
    public void validateEmailAddress(FacesContext context, UIComponent component, Object value) {
        try {
            InternetAddress emailAddr = new InternetAddress((String) value);
            emailAddr.validate();
        } catch (AddressException ex) {
            throw new ValidatorException(new FacesMessage("Invalid Email Address"));
        }
    }
}
